package com.v9.system.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.v9.common.annotation.QueryField;
import com.v9.common.dto.PageInfoDto;
import com.v9.common.dto.StringId;
import com.v9.common.dto.UserDto;
import com.v9.common.exception.BizException;
import com.v9.common.model.GenderTypeEnum;
import com.v9.common.security.MD5;
import com.v9.common.utils.QueryType;
import com.v9.common.web.AbstractController;
import com.v9.system.domain.DeptInfo;
import com.v9.system.domain.RoleInfo;
import com.v9.system.domain.UserInfo;
import com.v9.system.service.DeptInfoService;
import com.v9.system.service.RoleInfoService;
import com.v9.system.service.UserInfoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author lunshi
 */
@RestController
@Tag(name = "用户")
@Slf4j
@RequestMapping(value = "/system/user", method = RequestMethod.POST)
public class UserController extends AbstractController {

    @Resource
    private UserInfoService userInfoService;

    @Resource
    private DeptInfoService deptInfoService;
    @Resource
    private RoleInfoService roleInfoService;

    @RequestMapping(value = "add")
    @Operation(summary = "添加")
    public void add(@RequestBody UserInfoAddDto dto) {
        UserInfo info = clone(UserInfo.class, dto);
        info.setPassword(MD5.MD5Str(dto.getPassword()));
        if (StringUtils.isNotBlank(dto.getPhone())) {
            QueryWrapper<UserInfo> query = new QueryWrapper<>();
            query.eq("phone", dto.getPhone());
            query.or().eq("email", dto.getEmail());
            query.or().eq("user_name", dto.getUsername());
            Long count = userInfoService.selectCount(query);
            if (count > 0) {
                throw new BizException("用户已存在");
            }
        }
        info.setStatus(true);
        info.setDelStatus(false);
        DeptInfo byId = deptInfoService.findById(info.getDeptId());
        info.setDeptIds(byId.getIds() + "|" + byId.getId());
        userInfoService.insert(info);
        userInfoService.bindRole(info.getPin(), dto.getRoleIds());
    }

    @RequestMapping(value = "save")
    @Operation(summary = "修改")
    public void save(@RequestBody UserInfoSaveDto dto) {
        UserInfo info = clone(UserInfo.class, dto);
        info.setUsername(null);
        info.setPassword(null);
        DeptInfo byId = deptInfoService.findById(info.getDeptId());
        info.setDeptIds(byId.getIds() + "|" + byId.getId());
        userInfoService.updateById(info);
        userInfoService.bindRole(info.getPin(), dto.getRoleIds());
    }

    @RequestMapping(value = "view")
    @Operation(summary = "查看")
    public UserInfoViewDto view(@RequestBody StringId dto) {
        UserInfo byId = userInfoService.findById(dto.getId());
        List<Long> collect = roleInfoService.queryByPin(dto.getId()).stream().map(RoleInfo::getId).collect(Collectors.toList());
        UserInfoViewDto result = clone(UserInfoViewDto.class, byId);
        result.setRoleIds(collect);
        return result;
    }


    @RequestMapping(value = "list")
    @Operation(summary = "查询")
    public Page<UserInfoSearchResultDto> list(@RequestBody UserInfoQueryDto dto) {
        String deptIds = null;
        if (dto.getDeptId() != null) {
            DeptInfo dept = deptInfoService.findById(dto.getDeptId());
            dto.setDeptId(null);
            if (dept.getIds() != null) {
                deptIds = dept.getIds() + "|" + dept.getId();
            } else {
                deptIds = String.valueOf(dept.getId());
            }
        }
        QueryWrapper queryWrapper = buildQuery(dto);
        if (deptIds != null) {
            queryWrapper.like(getColumnToField("deptIds"), deptIds);
        }
        Page<UserInfo> userInfos = userInfoService.queryByPage(queryWrapper, dto.getPageable());
        Page<UserInfoSearchResultDto> clone = clone(UserInfoSearchResultDto.class, userInfos);
        return clone;
    }

    @RequestMapping(value = "changeStatus")
    @Operation(summary = "启用")
    public void changeStatus(@RequestBody ChangeStatusDto dto) {
        userInfoService.save(dto.getId(), "status", dto.getStatus());
    }

    @RequestMapping(value = "/reset/changePass")
    @Operation(summary = "重置密码")
    public void changePass(@RequestBody ChangeUserPassDto dto) {
        UserInfo info = new UserInfo();
        info.setId(dto.getId());
        info.setPassword(MD5.MD5Str(dto.getPass()));
        userInfoService.updateById(info);
        jwtTokenUtils.delLoginUserByPin(dto.getId());
    }

    @RequestMapping("/delete")
    @Operation(summary = "删除用户")
    public void delete(@RequestBody StringId dto) {
        userInfoService.remove(dto.getId());
    }

    @RequestMapping("/info")
    @Operation(summary = "用户信息")
    public Map<String, Object> info() {
        return buildMessage(() -> {
            Map<String, Object> results = new HashMap<>();
            results.put("permissions", List.of("*.*.*"));
            results.put("roles", List.of("admin", "common"));
            UserDto user = getUser();
            results.put("userName", user.getUsername());
            results.put("avatar", "");
            return results;
        });
    }

    @Data
    public static class UserInfoViewDto extends UserInfoSearchResultDto {
        private List<Long> roleIds;
    }

    @Data
    public static class ChangeStatusDto {
        String id;
        private Boolean status;
    }

    @Data
    public static class UserInfoAddDto {
        @Schema(description = "登录名称")
        private String username;
        @Schema(description = "真实名称")
        private String realName;
        @Schema(description = "签名")
        private String sign;
        @Schema(description = "生日")
        private Date birthday;
        @Schema(description = "密码")
        private String password;
        @Schema(description = "部门ID")
        private Long deptId;
        @Schema(description = "岗位")
        private Long positionId;
        @Schema(description = "用户邮箱")
        private String nickName;
        @Schema(description = "用户邮箱")
        private String email;
        @Schema(description = "手机号码")
        private String phone;
        @Schema(description = "用户性别")
        private GenderTypeEnum genderType;
        @Schema(description = "用户头像")
        private String icon;
        @Schema(description = "状态")
        private Boolean status;
        private List<Long> roleIds;
        @Schema(description = "备注")
        private String remark;
    }

    @Data
    public static class UserInfoSaveDto extends UserInfoAddDto {
        private String id;

    }

    @Data
    public static class UserInfoSearchResultDto {
        private String id;
        @Schema(description = "登录名称")
        private String username;
        @Schema(description = "真实名称")
        private String realName;
        @Schema(description = "签名")
        private String sign;
        @Schema(description = "生日")
        private Date birthday;
        @Schema(description = "密码")
        private String password;
        @Schema(description = "部门ID")
        private Long deptId;
        @Schema(description = "岗位")
        private Long positionId;
        @Schema(description = "岗位名称")
        private String positionName;
        @Schema(description = "用户邮箱")
        private String nickName;
        @Schema(description = "用户邮箱")
        private String email;
        @Schema(description = "手机号码")
        private String phone;
        @Schema(description = "用户性别")
        private GenderTypeEnum genderType;
        @Schema(description = "用户头像")
        private String icon;
        @Schema(description = "状态")
        private Boolean status;
        @Schema(description = "状态")
        private String loginIp;
        @Schema(description = "最后登录时间")
        private Date loginDate;

        private String remark;
        private Date createTime;

    }

    @Data
    public static class UserInfoQueryDto extends PageInfoDto {
        @QueryField(queryType = QueryType.LIKE)
        private String username;
        private String phone;
        private Long deptId;
        private Boolean status;
    }

    @Data
    public static class ChangeUserPassDto {
        @Schema(description = "账户id")
        private String id;
        @Schema(description = "密码")
        private String pass;
    }
}
